package com.finalministry.server;

import geodb.GeoDB;

import java.awt.Desktop;
import java.net.URI;

import javax.ws.rs.core.UriBuilder;

import org.finalministry.database.FinalministryDatabase;
import org.finalministry.database.connection.FinalministryDatabaseConnection;
import org.finalministry.database.dao.DaoFactory;
import org.finalministry.utils.DatabaseInitializer;
import org.finalministry.utils.geo.GeoUtils;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.http.server.StaticHttpHandler;
import org.glassfish.jersey.grizzly2.GrizzlyHttpServerFactory;
import org.glassfish.jersey.media.json.JsonJacksonModule;
import org.glassfish.jersey.server.Application;
import org.glassfish.jersey.server.ResourceConfig;

public class FinalministryWebServer {

	private static final String USERNAME = "sa";
	private static final String PASSWORD = "sa";

	private static final String FINALMINISTRY_DB_NAME = "finalministryTest";

	public static String contentUrl;

	private static final String CONTENT_PATH = "/finalministry";

	public static int portWebserver = 80;
	public static int portDatabase = 7786;

	public static void main(String[] args) throws Exception {

		if (args.length == 2) {
			try {
				portWebserver = Integer.parseInt(args[0]);
				portDatabase = Integer.parseInt(args[1]);
			} catch (Exception e) {
				System.err.println("Your delivered arguments cannot be transformed into integer values.");
				System.err.println(e);
				System.err.println("-------------");
				System.err.println("Exiting application.");
				System.exit(0);
			}
		} else {
			System.out.println("Starting in default mode ...");
			System.out
					.println("If you want to start the server with your own paramaters, ARGUMENT 1 is the port for the webserver, and ARGUMENT 2 the port for the H2 database.");
		}

		initDatabase(portDatabase);
		initWebserver(portWebserver);
	}

	private static void initWebserver(int port) throws Exception {

		final URI baseUri = UriBuilder.fromUri("http://localhost").port(port).build();
		final Application application = Application.builder(
				ResourceConfig.builder().packages(FinalministryWebServer.class.getPackage().getName()).build()).build();
		application.addModules(new JsonJacksonModule());
		final HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(baseUri, application);
		httpServer.getServerConfiguration().addHttpHandler(new StaticHttpHandler("src/main/resources/web"), CONTENT_PATH);

		for (NetworkListener networkListener : httpServer.getListeners()) {
			if (System.getenv("FILE_CACHE_ENABLED") == null) {
				networkListener.getFileCache().setEnabled(false);
			}
		}

		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				httpServer.stop();
			}
		});

		contentUrl = System.getenv("CONTENT_URL") != null ? System.getenv("CONTENT_URL") : CONTENT_PATH;

		/*
		 * Open the page in the browser after few seconds
		 */
		openWebpage(new URI("http://localhost:" + String.valueOf(portWebserver)));

		Thread.currentThread().join();
	}

	private static void initDatabase(int port) throws Exception {

		FinalministryDatabase database = new FinalministryDatabase(FINALMINISTRY_DB_NAME, USERNAME, PASSWORD, port);
		database.start();
		GeoUtils.database = database;
		DaoFactory.setFinalMinistryConnection(new FinalministryDatabaseConnection(FINALMINISTRY_DB_NAME, USERNAME, PASSWORD, port));
		DaoFactory.getInstance();
		System.out.println("Database is alive = " + DaoFactory.getInstance().isConnectionActive() + " on port " + port);
		DatabaseInitializer.forceDatabaseSpatialOnlyInitialization(DaoFactory.getFinalMinistryConnection());

		try {
			GeoDB.InitGeoDB(DaoFactory.getFinalMinistryConnection().getConnection());
		} catch (Exception e) {
			System.err.println("Error while initializing spatial methods for database ... ");
			e.printStackTrace();
			database.stopServer();
			System.exit(0);
		}

	}

	public static void openWebpage(URI uri) {
		Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
		if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
			try {
				System.out.println("I try to open the browser for the url " + uri.toString());
				desktop.browse(uri);
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			System.out.println("Please open your browser and type in this URL: " + uri.toString());
		}
	}
}